﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Shapes;

namespace RayGraphComponent
{
    public sealed class Serie
    {
        private LineGraph graph;

        public string Title
        {
            private set;
            get;
        }

        public double MinY
        {
            private set;
            get;
        }

        public double MaxY
        {
            private set;
            get;
        }

        public double MinX
        {
            private set;
            get;
        }

        public double MaxX
        {
            private set;
            get;
        }

        public Path UIElement
        {
            get;
            set;
        }

        public Brush Color
        {
            get;
            set;
        }

        public int ShiftSize
        {
            get;
            set;
        }

        public event RoutedEventHandler DataUpdated;

        private IList<Point> data;

        public IList<Point> Data
        {
            set
            {
                this.SetData(value);
            }
            get
            {
                return this.data;
            }
        }

        public Serie(LineGraph parent, string title)
        {
            this.graph = parent;

            this.data = new List<Point>();

            this.MinY = Double.NaN;
            this.MaxY = Double.NaN;

            this.MinX = Double.NaN;
            this.MaxX = Double.NaN;

            this.Title = title;

            this.ShiftSize = 100;
        }

        public void SetData(IList<Point> data)
        {
            this.data = data;
            this.CalculateMinMax();

            this.OnDataUpdated(new RoutedEventArgs());
        }

        private void OnDataUpdated(RoutedEventArgs e)
        {
            if (this.DataUpdated != null)
            {
                this.DataUpdated(this, e);
            }
        }

        public void AddPoint(Point p, bool shift)
        {
            if (this.Data.Count == 0)
            {
                this.Data.Add(p);
                this.CalculateMinMax();
                this.OnDataUpdated(new RoutedEventArgs());
            }
            else if (p.X > this.Data.Last().X)
            {
                if (shift && this.Data.Count >= this.ShiftSize)
                {
                    int loops = this.Data.Count - this.ShiftSize;

                    for (int i = 0; i < loops; i++)
                    {
                        Debug.WriteLine("MIN X : {0}", this.Data[i].ToString());
                        this.Data.RemoveAt(i);
                    }
                }

                this.Data.Add(p);
                this.CalculateMinMax();
                this.OnDataUpdated(new RoutedEventArgs());
            }

            Debug.WriteLine("MAX X : {0}", p.ToString());
        }

        private void CalculateMinMax()
        {
            this.MinY = Double.NaN;
            this.MaxY = Double.NaN;
            this.MinX = Double.NaN;
            this.MaxX = Double.NaN;

            foreach (Point p in data)
            {
                if (Double.IsNaN(this.MinY) || p.Y < this.MinY)
                {
                    this.MinY = p.Y;
                }
                if (Double.IsNaN(this.MaxY) || p.Y > this.MaxY)
                {
                    this.MaxY = p.Y;
                }
                if (Double.IsNaN(this.MinX) || p.X < this.MinX)
                {
                    this.MinX = p.X;
                }
                if (Double.IsNaN(this.MaxX) || p.X > this.MaxX)
                {
                    this.MaxX = p.X;
                }
            }
        }
    }
}
